package com.rpa.server.servicerpaserver.crawler.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rpa.secure.servicerpasecure.common.constant.MessageConstant;
import com.rpa.secure.servicerpasecure.common.constant.RegularConstant;
import com.rpa.secure.servicerpasecure.common.exception.RpaRegisterException;
import com.rpa.server.servicerpaserver.crawler.entity.CeekSetting;
import com.rpa.server.servicerpaserver.crawler.entity.Clazz;
import com.rpa.server.servicerpaserver.crawler.entity.Course;
import com.rpa.server.servicerpaserver.crawler.entity.User;
import com.rpa.server.servicerpaserver.crawler.entity.dto.ActiveDto;
import com.rpa.server.servicerpaserver.crawler.entity.dto.TestDto;
import com.rpa.server.servicerpaserver.crawler.entity.dto.WorkDto;
import com.rpa.server.servicerpaserver.crawler.operate.*;
import com.rpa.server.servicerpaserver.crawler.service.CeekSettingService;
import com.rpa.server.servicerpaserver.crawler.service.ClazzService;
import com.rpa.server.servicerpaserver.crawler.service.CourseService;
import com.rpa.server.servicerpaserver.crawler.service.UserService;
import com.rpa.server.servicerpaserver.crawler.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;

/**
 * @author 十元
 * @description 针对表【rpa_user(教务管理系统用户表)】的数据库操作Service实现
 * @createDate 2025-01-10 11:41:25
 */
@Service
@Slf4j
public class UerServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    @Autowired
    @Lazy
    private LogonOperate logonOperate;

    @Autowired
    @Lazy
    private CourseOperate courseOperate;
    @Autowired
    @Lazy
    private ClazzOperate clazzOperate;
    @Autowired
    @Lazy
    private ActiveOperate activeOperate;
    @Autowired
    @Lazy
    private TestOperate testOperate;
    @Autowired
    @Lazy
    private WorkOperate workOperate;
    @Autowired
    private CourseService courseService;
    @Autowired
    private CeekSettingService ceekSettingService;
    @Autowired
    private ClazzService clazzService;


    @Override
    public User register(User user) {
        String uname = user.getRpaAccount();
        String password = user.getRpaPassword();

        // 验证手机号格式
        if (!Pattern.matches(RegularConstant.PHONE_NUMBER, uname)) {
            throw new RpaRegisterException(MessageConstant.NO_PHONE);
        }

        // 验证密码格式
        if (!Pattern.matches(RegularConstant.PASSWORD_NUMBER, password)) {
            throw new RpaRegisterException(MessageConstant.NO_PASSWORD);
        }

        // 检查账户是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getRpaAccount, uname);
        List<User> rpaRegisterList = baseMapper.selectList(queryWrapper);

        if (!rpaRegisterList.isEmpty()) {
            throw new RpaRegisterException(MessageConstant.IS_LOGIN);
        }

        // 插入新用户
        baseMapper.insert(user);
        String accountId = user.getId().toString();
        //初始化
       initData(accountId);

        return user;
    }

    @Async
    public void initData(String accountId) {
        // 初始化登录
        CompletableFuture<Boolean> logonFuture = logonOperate.logonCX(Long.parseLong(accountId));

        logonFuture.thenAccept(isSuccess -> {
            if (isSuccess) {
                // 获取头像信息
                CompletableFuture<Boolean> nameAndPictureFuture = courseOperate.getNameAndPicture(accountId);
                // 获取课程信息
                CompletableFuture<Boolean> courseFuture = courseOperate.getCourse(accountId);

                // 使用 allOf 确保两个任务都完成后继续
                CompletableFuture.allOf(nameAndPictureFuture, courseFuture).thenRunAsync(() -> {
                    LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(Course::getAccountId, accountId);
                    courseService.list(queryWrapper).forEach(course -> {
                        // 获取课程对应班级信息
                        CompletableFuture<Boolean> classFuture = clazzOperate.getClass(course.getAccountId().toString(), course.getCourseId());

                        // 确保班级信息获取成功后初始化签到扣分
                        classFuture.thenRunAsync(() -> saveCeekSetting(course))
                                .exceptionally(ex -> {
                                    // 处理异常
                                    ex.printStackTrace();
                                    return null;
                                });
                    });
                }).exceptionally(ex -> {
                    // 处理异常
                    ex.printStackTrace();
                    return null;
                });
            }
        }).exceptionally(ex -> {
            // 处理异常
            ex.printStackTrace();
            return null;
        });
    }

    @Async("saveCeekSettingTaskExecutor")
    public void saveCeekSetting(Course courses ) {
        QueryWrapper<Clazz> clazzLambdaQueryWrapper = new QueryWrapper<>();
        clazzLambdaQueryWrapper.select("DISTINCT account_id,course_id,clazz_id")
                .lambda()
                .eq(Clazz::getAccountId, courses.getAccountId())
                .eq(Clazz::getCourseId, courses.getCourseId());
        List<CeekSetting> ceekSettings = new LinkedList<>();
        int size = clazzService.listMaps(clazzLambdaQueryWrapper).size();
        log.error(size+"---------------------------------------");
        clazzService.listMaps(clazzLambdaQueryWrapper)
                .forEach(clazz -> {
                    CeekSetting build = CeekSetting.builder()
                            .accountId(MapUtil.getStr(clazz, "account_id",""))
                            .courseId(MapUtil.getStr(clazz, "course_id",""))
                            .clazzId(MapUtil.getStr(clazz, "clazz_id",""))
                            .beLate(2)
                            .leaveEarly(2)
                            .absenceFromDuty(2)
                            .build();
                    ActiveDto activeDto = new ActiveDto() {{
                        setAccountId(MapUtil.getStr(clazz, "account_id",""));
                        setCourseId(MapUtil.getStr(clazz, "course_id",""));
                        setClassId(MapUtil.getStr(clazz, "clazz_id",""));
                    }};
                    TestDto testDto = new TestDto() {{
                        setAccountId(MapUtil.getStr(clazz, "account_id",""));
                        setCourseId(MapUtil.getStr(clazz, "course_id",""));
                        setClassId(MapUtil.getStr(clazz, "clazz_id",""));
                    }};
                    WorkDto workDto = new WorkDto() {{
                        setAccountId(MapUtil.getStr(clazz, "account_id",""));
                        setCourseId(MapUtil.getStr(clazz, "course_id",""));
                        setClassId(MapUtil.getStr(clazz, "clazz_id",""));
                    }};
                    activeOperate.getActive(activeDto);
                    testOperate.getTest(testDto);
                    workOperate.getWork(workDto);
                    ceekSettings.add(build);
                });
        if (CollUtil.isNotEmpty(ceekSettings)){
            ceekSettingService.saveBatch(ceekSettings);
        }
    }

    @Override
    public User login(User user) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getRpaAccount, user.getRpaAccount())
                .eq(User::getRpaPassword, user.getRpaPassword());
        User users = baseMapper.selectOne(queryWrapper);
        if (users != null) {
            logonOperate.logonCX(user.getId());
            return users;
        } else {
            throw new RpaRegisterException(MessageConstant.NO_UNAME_PASSWORD);
        }
    }
}




